package top.superxuqc.autocheckincqupt.checkinservice.service.imp;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import top.superxuqc.autocheckincqupt.api.CheckInService;
import top.superxuqc.autocheckincqupt.checkinservice.service.constants.ConnectUrlConstants;
import top.superxuqc.autocheckincqupt.domain.ApiResult;


import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 请填写类的描述
 *
 * @author xuqicheng1
 * @date 2021-07-15 18:34
 */
@Service
public class CheckInServiceImp implements CheckInService {


        private RestTemplate template = new RestTemplate();
        /**
         * 日志记录
         */
        private final static Logger LOGGER = LoggerFactory.getLogger(CheckInServiceImp.class);

        /**
         *
         * @param openId opendId
         * @param xh    xh
         * @param address   address
         * @param qq  此处为qq号
         * @return
         */
        @Override
        public ApiResult<List<String>> startCheckIn(String openId, String xh, String address, String qq){
                LOGGER.debug("CheckInServiceImp start deal xh={} qq={}",xh,qq);
                ApiResult<List<String>> apiResult = new ApiResult<>(new ArrayList<>());
                boolean b = checkIschecked(xh, apiResult);
                if(!b || apiResult.getCode().equals("400")){
                        return apiResult;
                }
                Map<String, String> studentInfo = getStudentInfo(xh, apiResult);
                if(apiResult.getCode().equals("400")){
                        return apiResult;
                }

                Map<String, String> location = getLocation(address, apiResult);
                if(apiResult.getCode().equals("400")){
                        return apiResult;
                }
                Map<String, String> map = new HashMap<>();
                map.putAll(location);
                map.putAll(studentInfo);
                map.put("xxdz",address);
                map.put("xh",xh);
                map.put("openid",openId);
                map.put("ywjcqzbl","低风险");
                map.put("ywjchblj","无");
                map.put("xjzdywqzbl","无");
                map.put("ywytdzz","无");
                map.put("beizhu","无");
                map.put("twsfzc","是");
                Date date = new Date(System.currentTimeMillis());
                DateFormat dateFormatD = new SimpleDateFormat("dd");
                DateFormat dateFormatH = new SimpleDateFormat("hh");
                String D = dateFormatD.format(date);
                String H = dateFormatH.format(date);
                map.put("mrdkkey", ConnectUrlConstants.dateCode[Integer.valueOf(D)]+ ConnectUrlConstants.hourCode[Integer.valueOf(H)]);
                map.put("timestamp",String.valueOf(System.currentTimeMillis()/1000));
                String parmas = Base64.getEncoder().encodeToString(JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8));
                checkIn(parmas,apiResult);
                String msg = "";
                for (String data:apiResult.getData()
                     ) {
                        msg += data;
                }
                sendGroupKey(msg,qq,apiResult);
                return apiResult;
        }

        @Override
        public boolean checkIschecked(String xh, ApiResult<List<String>> apiResult){
                HashMap<String,String> params = new HashMap<>();
                params.put("xh",xh);
                params.put("timestamp",String.valueOf(System.currentTimeMillis()/1000));
                String jsonParams = JSON.toJSONString(params);
                String key = Base64.getEncoder().encodeToString(jsonParams.getBytes(StandardCharsets.UTF_8));
                MultiValueMap<String,String> map = new LinkedMultiValueMap<>();
                map.add("key", key);
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map,new HttpHeaders());
                try {
                        ResponseEntity<String> response = template.postForEntity(ConnectUrlConstants.CHECK_REPEAT_CLOCK_URL, request, String.class);
                        JSONObject result = JSONObject.parseObject(response.getBody());
                        LOGGER.debug("checkIschecked xh = {}, result = {}",xh,result.toJSONString());
                        if(result.getInteger("status") == 200) {
                                Integer integer = result.getJSONObject("data").getInteger("count");
                                if(integer == 0){
                                        apiResult.getData().add("1.今日首次打卡，开始打卡\n");
                                        apiResult.success();
                                }else {
                                        apiResult.getData().add("1.今日已经打卡，结束\n");
                                        apiResult.success();
                                        apiResult.setCode("201");
                                        return false;
                                }
                        }else {
                                apiResult.getData().add("1.请求验证是否已经打卡服务器失败\n");
                                apiResult.fail("请求验证是否已经打卡服务器失败");
                                return false;
                        }
                } catch (Exception e) {
                        LOGGER.error("#checkIschecked error = {}",e.getMessage());
                        e.printStackTrace();
                        apiResult.getData().add("1.请求验证是否已经打卡出错\n");
                        apiResult.fail("请求验证是否已经打卡出错");
                        return false;
                }
                return true;
        }

        /**
         * 获取name和gender
         * @param xh
         * @param apiResult
         * @return
         */
        @Override
        public Map<String,String> getStudentInfo(String xh, ApiResult<List<String>> apiResult){
                HashMap<String,String> map = new HashMap<>();
                try {
                        String body = template.getForEntity(ConnectUrlConstants.GET_STUDENT_INFO_URL + "?stu=" + xh, String.class).getBody();
                        LOGGER.debug("getStudentInfo xh = {} ,result = {}",xh,body);
                        JSONObject result = JSONObject.parseObject(body);
                        if(result.getInteger("status") == 200) {
                                JSONObject info = result.getJSONArray("data").getJSONObject(0);
                                map.put("name",info.getString("name"));
                                map.put("xb",info.getString("gender"));
                                apiResult.getData().add("2.获取学生信息成功\n");
                                apiResult.success();
                        }else {
                                apiResult.getData().add("2.请求获取学生信息服务器失败\n");
                                apiResult.fail("请求获取学生信息服务器失败");
                                return new HashMap<>();
                        }
                } catch (Exception e) {
                        LOGGER.error("#getStudentInfo error = {}",e.getMessage());
                        e.printStackTrace();
                        apiResult.getData().add("2.获取学生信息出错\n");
                        apiResult.fail("获取学生信息出错");
                        return new HashMap<>();
                }


                return map;
        }

        @Override
        public Map<String,String> getLocation(String address, ApiResult<List<String>> apiResult){
                HashMap<String,String> map = new HashMap<>();
                try {
                        String body = template.getForEntity(ConnectUrlConstants.GET_LOCATION_URL + "?address=" + address+"&key=" + ConnectUrlConstants.MAP_API_KEY, String.class).getBody();
                        LOGGER.debug("getLocation address = {},result = {}",address,body);
                        JSONObject result = JSONObject.parseObject(body);
                        if(result.getInteger("status") == 0) {
                                map.put("longitude",result.getJSONObject("result").getJSONObject("location").getString("lng"));
                                map.put("latitude",result.getJSONObject("result").getJSONObject("location").getString("lat"));
                                JSONObject addressInfo = result.getJSONObject("result").getJSONObject("address_components");
                                String addressBig = addressInfo.getString("province")+","+addressInfo.getString("city")+","+addressInfo.getString("district");
                                map.put("szdq",addressBig);
                                String locationSmall = addressInfo.getString("city")+","+addressInfo.getString("district")+","+result.getJSONObject("result").getString("title");
                                map.put("locationSmall",locationSmall);
                                map.put("locationBig","中国,"+addressBig);
                                apiResult.getData().add("3.获取位置信息成功\n");
                                apiResult.success();
                        }else {
                                System.out.println(result.toJSONString());
                                LOGGER.error("#请求获取位置信息成服务器失败 {}",result.toJSONString());
                                apiResult.getData().add("3.请求获取位置信息成服务器失败\n");
                                apiResult.fail("请求获取位置信息成服务器失败");
                                return new HashMap<>();
                        }
                } catch (Exception e) {
                        LOGGER.error("#getLocation error = {}",e.getMessage());
                        e.printStackTrace();
                        apiResult.getData().add("3.获取位置信息出错\n");
                        apiResult.fail("获取位置信息出错");
                        return new HashMap<>();
                }
                return map;
        }

        @Override
        public boolean checkIn(String params, ApiResult<List<String>> apiResult){
                MultiValueMap<String,String> map = new LinkedMultiValueMap<>();
                map.add("key",params);
                HttpHeaders header = new HttpHeaders();
                header.add("User-Agent","Mozilla/5.0 (Linux; Android 10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2693 MMWEBSDK/201001 Mobile Safari/537.36 MMWEBID/7311 MicroMessenger/7.0.20.1781(0x27001439) Process/appbrand2 WeChat/arm64 NetType/4G Language/zh_CN ABI/arm64");
                header.add("Referer","https://servicewechat.com/wx8227f55dc4490f45/76/page-frame.html");
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, header);
                try {
                        ResponseEntity<String> response = template.postForEntity(ConnectUrlConstants.CHECK_IN_URL, request, String.class);
                        JSONObject result = JSONObject.parseObject(response.getBody());
                        LOGGER.debug("checkIn result = {}",result.toJSONString());
                        if(result.getInteger("status") == 200) {
                                apiResult.getData().add("4.打卡成功\n");
                                apiResult.success();
                        }else {
                                apiResult.getData().add("4.请求打卡服务器失败\n");
                                apiResult.fail("请求打卡服务器失败");
                                return false;
                        }
                } catch (Exception e) {
                        LOGGER.error("#checkIn error = {}",e.getMessage());
                        e.printStackTrace();
                        apiResult.getData().add("4.打卡出错\n");
                        apiResult.fail("打卡出错");
                        return false;
                }
                return true;

        }

        @Override
        public boolean sendGroupKey(String msg,String qq,ApiResult<List<String>> apiResult){
                MultiValueMap<String,String> map = new LinkedMultiValueMap<>();
                map.add("msg", "@at="+qq+"@\n"+msg);
                HttpHeaders header = new HttpHeaders();
                header.add("Content-Type","application/x-www-form-urlencoded");
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, header);
                try {

                        ResponseEntity<String> response = template.postForEntity(ConnectUrlConstants.QMSG_KEY_GROUP, request, String.class);
                        String body = response.getBody();
                        LOGGER.debug("sendGroupKey result = {}",body);
                        if(response.getStatusCodeValue()!= 200){
                                LOGGER.error("#sendGroupKey error = {}",body);
                        }else {
                                while (JSONObject.parseObject(body).getInteger("code") == 500){
                                        LOGGER.debug("#sendGropKey 频繁，等待1s");
                                        Thread.sleep(1000);
                                        response = template.postForEntity(ConnectUrlConstants.QMSG_KEY_GROUP, request, String.class);
                                        body = response.getBody();
                                }
                        }
                } catch (Exception e) {
                        LOGGER.error("#sendGroupKey error = {}",e.getMessage());
                        e.printStackTrace();
                        apiResult.getData().add("5.发送给群组\n");
                        apiResult.fail("发群组出错");
                        return false;
                }
                return true;
        }
}
